{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# HBMQTT\n",
    "\n",
    "## 简介\n",
    "\n",
    "开源的Mqtt客户端和broker，使用python标准异步库`asyncio`实现，提供协程并发程序开发的直接API。\n",
    "\n",
    "- GitHub：https://github.com/beerfactory/hbmqtt\n",
    "- 文档：https://hbmqtt.readthedocs.io/en/latest/\n",
    "\n",
    "## Feature\n",
    "\n",
    "HBMQTT实现了完整的MQTT 3.1.1协议规范，并提供了以下特性：\n",
    "\n",
    "- Support QoS 0, QoS 1 and QoS 2 messages flow\n",
    "- 客户端断线自动重连\n",
    "- 通过密钥文件认证（其他方法可通过插件系统实现）\n",
    "- 基础的`$SYS` topics 支持\n",
    "- TCP 和 websocket 支持\n",
    "- TCP 和 websocket 的 SSL 支持\n",
    "- 插件系统\n",
    "\n",
    "## 依赖\n",
    "\n",
    "要求Python >=3.4.3\n",
    "\n",
    "## 安装\n",
    "\n",
    ">pip install hbmqtt==0.9.6\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 命令行用法\n",
    "\n",
    "用于在程序外进行测试\n",
    "\n",
    "基本功能：\n",
    "\n",
    "- 指定 topic 发送消息到外部 MQTT broker\n",
    "- 订阅并接收发布的消息\n",
    "- 搭建一个 MQTT broker\n",
    "\n",
    "## 发布消息\n",
    "\n",
    "`hbmqtt_pub`是一个命令行工具，可以用于向 topic 发布一些消息。它需要一些参数，如：服务器地址、topic 主题、QoS 服务质量和要发送的数据。其他选项允许更复杂的用例。\n",
    "\n",
    "**[基本用法](https://hbmqtt.readthedocs.io/en/latest/references/hbmqtt_pub.html)**\n",
    "\n",
    "```sh\n",
    "hbmqtt_pub --version\n",
    "hbmqtt_pub (-h | --help)\n",
    "hbmqtt_pub --url BROKER_URL -t TOPIC (-f FILE | -l | -m MESSAGE | -n | -s) [-c CONFIG_FILE] [-i CLIENT_ID] [-d]\n",
    "           [-q | --qos QOS] [-d] [-k KEEP_ALIVE] [--clean-session]\n",
    "           [--ca-file CAFILE] [--ca-path CAPATH] [--ca-data CADATA]\n",
    "           [ --will-topic WILL_TOPIC [--will-message WILL_MESSAGE] [--will-qos WILL_QOS] [--will-retain] ]\n",
    "           [--extra-headers HEADER]\n",
    "```\n",
    "为了操作方便， `hbmqtt_pub`的大部分参数跟 [mosquitto_pub](http://mosquitto.org/man/mosquitto_pub-1.html) 一致.\n",
    "\n",
    "### 参数详细介绍\n",
    "\n",
    "| 参数|说明|\n",
    "|:---|:---|\n",
    "|--version|HBMQTT版本信息\n",
    "|-h, --help|显示帮助信息\n",
    "|-c|设置客户端运行YAML配置文件\n",
    "|-d|显示debug信息\n",
    "|--ca-file|定义包含受信任的PEM编码CA证书的文件路径. 用于开启SSL加密通信.\n",
    "|--ca-path|定义包含受信任的PEM编码CA证书的文件夹路径，用于开启SSL加密通信.\n",
    "|--ca-data|设置受信任的经过PEM编码的CA证书 用于开启SSL加密通信.\n",
    "|--clean-session| 如果提供该参数，将设置CONNECT 连接清除 session标志位 为True\n",
    "|-f|将文件的内容作为消息发送。该文件是逐行读取的，`hbmqtt_pub`将读取的每一行作为一条消息。\n",
    "|-i|客户端id，默认值为 hbmqtt/ + 随机字符\n",
    "|-l|发送从stdin读取的消息。hbmqtt pub将为读取的每一行发布一条消息。不会发送空行。\n",
    "|-k|设置客户端keep alive超时时间.\n",
    "|-m| 发送的消息消息内容\n",
    "|-n|发送一条空数据（长度为0）\n",
    "|-q, --qos|指定QoS消息服务质量，取值0，1和2，默认为0\n",
    "|-s|发送从stdin读取的消息，将整个内容作为单个消息发送。\n",
    "|-t|消息的topic\n",
    "|--url|Broker的 URL，支持的格式参考下文。\n",
    "|--will-topic|在客户端意外断开连接时，要发送的主题。\n",
    "|--will-message|指定由broker存储并在此客户端意外断开连接时发送的消息。这个必须和`--will-topic`参数一起使用。\n",
    "|--will-qos|用于 Will的QoS。默认值为0。这个必须和`--will-topic`参数一起使用。\n",
    "|--will-retain|如果给定，如果客户端意外断开连接，发送出去的消息将被视为retain消息。这个必须和`--will-topic`一起使用\n",
    "|--extra-headers| 指定一个JSON对象字符串，带有表示在初始连接上传输的附加头的键-值对，但仅在使用websocket连接时使用\n",
    "\n",
    "### 配置文件\n",
    "\n",
    "指定`-c` 参数，并传入一个 YAML文件路径，详细配置内容如下：\n",
    "\n",
    "\n",
    "| yaml字段 |  说明\n",
    "|:---------|:----------------|\n",
    "| keep_alive | Keep-alive 超时时间，默认 10 s\n",
    "| ping_delay | 在 keep-alive 超时之前发送的 Auto-ping 包的延迟，默认 1s，设置成 0 则表示禁用，但是会导致与 broker 断开连接\n",
    "| default_qos | 发布消息的默认 QoS。默认值为 0。\n",
    "| default_retain |消息发布的默认 retain 值，默认为`false`\n",
    "| auto_reconnect | 当与 broker 的连接中断，启用或禁用自动重新连接。默认值为 `false`\n",
    "| reconnect_retries | 最大重连重试次数，默认为 2 次\n",
    "| reconnect_max_interval | 两次重连之间的最大间隔，默认为10s\n",
    "\n",
    "### 示例\n",
    "\n",
    "以下示例可以跟  [mosquitto_pub](http://mosquitto.org/man/mosquitto_pub-1.html) 的文档适配\n",
    "\n",
    "#### 示例一\n",
    "\n",
    "发布数据123 到 /test 主题上，QoS 1: :\n",
    "\n",
    "```sh\n",
    "hbmqtt_pub --url mqtt://test.mosquitto.org -t /test -m 123  -q 1\n",
    "```\n",
    "\n",
    "#### 示例二\n",
    "\n",
    "向远程主机的非标准端口上，发布时间戳和温度信息， QoS=0\n",
    "\n",
    "```sh\n",
    "hbmqtt_pub --url mqtt://192.168.1.1:1885 -t sensors/temperature -m \"1266193804 32\"\n",
    "```\n",
    "\n",
    "#### 示例三\n",
    "\n",
    "发送文件内容的两种方式\n",
    "\n",
    "```sh\n",
    "hbmqtt_pub --url mqtt://localhost -t my/topic -f ./data\n",
    "\n",
    "hbmqtt_pub --url mqtt://localhost -t my/topic -s < ./data\n",
    "```\n",
    "\n",
    "#### 发送 websocket 消息\n",
    "\n",
    "将温度信息封装到websocket中，向localhost发布，添加额外header，QoS=1\n",
    "\n",
    "```sh\n",
    "hbmqtt_pub --url wss://localhost -t sensors/temperature -m 32 -q 1 --extra-headers '{\"Authorization\": \"Bearer <token>\"}'\n",
    "```\n",
    "\n",
    "#### 管道符输入\n",
    "\n",
    "hbmqtt_pub 可以从文件或 stdin 中读取数据，并将读取的数据作为消息载荷发送\n",
    "\n",
    "```sh\n",
    "$ some_command | hbmqtt_pub --url mqtt://localhost -t /test -l\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 订阅消息\n",
    "\n",
    "`hbmqtt_sub`是一个命令行工具，可用于订阅 broker 上的某些 pattern，并从其他 MQTT 客户机发布的与这些 patern 匹配的主题上的消息中获取日期。\n",
    "\n",
    "**基本用法**\n",
    "\n",
    "```sh\n",
    "hbmqtt_sub --version\n",
    "hbmqtt_sub (-h | --help)\n",
    "hbmqtt_sub --url BROKER_URL -t TOPIC... [-n COUNT] [-c CONFIG_FILE] [-i CLIENT_ID] [-q | --qos QOS] [-d]\n",
    "           [-k KEEP_ALIVE] [--clean-session] [--ca-file CAFILE] [--ca-path CAPATH] [--ca-data CADATA]\n",
    "           [ --will-topic WILL_TOPIC [--will-message WILL_MESSAGE] [--will-qos WILL_QOS] [--will-retain] ]\n",
    "           [--extra-headers HEADER]\n",
    "```\n",
    "\n",
    "为了操作方便， hbmqtt_sub 的大部分参数跟 [mosquitto_sub](http://mosquitto.org/man/mosquitto_sub-1.html) 一致.\n",
    "\n",
    "### 参数详细介绍\n",
    "\n",
    "| 参数            | 说明                                                                                                   |\n",
    "| :-------------- | :----------------------------------------------------------------------------------------------------- |\n",
    "| --version       | HBMQTT 版本信息                                                                                        |\n",
    "| -h, --help      | 显示帮助信息                                                                                           |\n",
    "| -c              | 设置客户端运行 YAML 配置文件                                                                           |\n",
    "| -d              | 显示 debug 信息                                                                                        |\n",
    "| --ca-file       | 定义包含受信任的 PEM 编码 CA 证书的文件路径. 用于开启 SSL 加密通信.                                    |\n",
    "| --ca-path       | 定义包含受信任的 PEM 编码 CA 证书的文件夹路径，用于开启 SSL 加密通信.                                  |\n",
    "| --ca-data       | 设置受信任的经过 PEM 编码的 CA 证书 用于开启 SSL 加密通信.                                             |\n",
    "| --clean-session | 如果提供该参数，将设置 CONNECT 连接清除 session 标志位 为 True                                         |\n",
    "| -i              | 客户端 id，默认值为 hbmqtt/ + 随机字符                                                                   |\n",
    "| -l              | 发送从 stdin 读取的消息。hbmqtt pub 将为读取的每一行发布一条消息。不会发送空行。                       |\n",
    "| -k              | 设置客户端 keep alive 超时时间.                                                                        |\n",
    "| -n              | 在结束前接收的消息数量，默认不断接收                                                                   |\n",
    "| -q, --qos       | 指定用于接收消息的服务质量。此 QoS 在订阅请求中发送。                                                  |\n",
    "| -t              | 订阅 Topic 的过滤器                                                                                    |\n",
    "| --url           | Broker 的 URL，支持的格式参考下文。                                                                    |\n",
    "| --will-topic    | 在客户端意外断开连接时，要发送的主题。                                                                 |\n",
    "| --will-message  | 指定由 broker 存储并在此客户端意外断开连接时发送的消息。这个必须和`--will-topic`参数一起使用。         |\n",
    "| --will-qos      | 用于 Will 的 QoS。默认值为 0。这个必须和`--will-topic`参数一起使用。                                   |\n",
    "| --will-retain   | 如果给定，如果客户端意外断开连接，发送出去的消息将被视为 retain 消息。这个必须和`--will-topic`一起使用 |\n",
    "| --extra-headers | 指定一个 JSON 对象字符串，带有表示在初始连接上传输的附加头的键-值对，但仅在使用 websocket 连接时使用   |\n",
    "\n",
    "### 配置文件\n",
    "\n",
    "指定`-c` 参数，并传入一个 YAML 文件路径，详细配置内容如下：\n",
    "\n",
    "| yaml 字段              | 说明                                                                                                        |\n",
    "| :--------------------- | :---------------------------------------------------------------------------------------------------------- |\n",
    "| keep_alive             | Keep-alive 超时时间，默认 10 s                                                                              |\n",
    "| ping_delay             | 在 keep-alive 超时之前发送的 Auto-ping 包的延迟，默认 1s，设置成 0 则表示禁用，但是会导致与 broker 断开连接 |\n",
    "| default_qos            | 发布消息的默认 QoS。默认值为 0。                                                                            |\n",
    "| default_retain         | 消息发布的默认 retain 值，默认为`false`                                                                     |\n",
    "| auto_reconnect         | 当与 broker 的连接中断，启用或禁用自动重新连接。默认值为 `false`                                            |\n",
    "| reconnect_retries      | 最大重连重试次数，默认为 2 次                                                                               |\n",
    "| reconnect_max_interval | 两次重连之间的最大间隔，默认为 10s                                                                          |\n",
    "\n",
    "### 示例\n",
    "\n",
    "以下示例可以跟 [mosquitto_sub](http://mosquitto.org/man/mosquitto_sub-1.html) 的文档适配\n",
    "\n",
    "#### 示例一\n",
    "\n",
    "订阅 \\$SYS/: 下所有的消息， QoS=0\n",
    "\n",
    "```sh\n",
    "hbmqtt_sub --url mqtt://localhost -t '$SYS/#' -q 0\n",
    "```\n",
    "\n",
    "#### 示例二\n",
    "\n",
    "订阅 /# 下的 10 条消息， QoS=2\n",
    "\n",
    "```sh\n",
    "hbmqtt_sub --url mqtt://localhost -t /# -q 2 -n 10\n",
    "```\n",
    "\n",
    "#### 示例三\n",
    "\n",
    "订阅\\$SYS/ 下的所有通过 websocket 包装的消息，QoS=0，附加额外 headers\n",
    "\n",
    "```sh\n",
    "hbmqtt_sub --url wss://localhost -t '$SYS/#' -q 0 --extra-headers '{\"Authorization\": \"Bearer <token>\"}'\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## URL 格式\n",
    "\n",
    "参数 --url 必须符合以下格式\n",
    "\n",
    "```sh\n",
    "[mqtt|ws][s]://[username][:password]@host.domain[:port]\n",
    "```\n",
    "\n",
    "比如:\n",
    "\n",
    "```sh\n",
    "mqtt://localhost\n",
    "mqtt://localhost:1884\n",
    "mqtt://user:password@localhost\n",
    "ws://test.mosquitto.org\n",
    "wss://user:password@localhost\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 运行 broker\n",
    "\n",
    "`hbmqtt` 命令启动一个 broker\n",
    "\n",
    "### 基本用法\n",
    "\n",
    "```sh\n",
    "hbmqtt --version\n",
    "hbmqtt (-h | --help)\n",
    "hbmqtt [-c <config_file> ] [-d]\n",
    "```\n",
    "\n",
    "### 选项\n",
    "\n",
    "| 参数       | 说明                                                                    |\n",
    "|:---------- | :----------------------------------------------------------------------- |\n",
    "| --version  | HBMQTT version information                                              |\n",
    "| -h, --help | Display hbmqtt_sub usage help                                           |\n",
    "| -c         | Set the YAML configuration file to read and pass to the client runtime. |\n",
    "\n",
    "### 读配置文件\n",
    "\n",
    "指定 `-c`参数，传入一个 [YAML](http://yaml.org/) 文件名，该文件应包含以下配置：\n",
    "\n",
    "- listeners : 网络绑定列表\n",
    "- timeout-disconnect-delay : 在 keep-alive 超时后客户端断开连接的时间\n",
    "- auth : 认证配置\n",
    "\n",
    "YAML 文件基础配置如下:\n",
    "\n",
    "```yaml\n",
    "listeners:\n",
    "  default:\n",
    "    type: tcp\n",
    "    bind: 0.0.0.0:1883\n",
    "sys_interval: 20\n",
    "timeout-disconnect-delay: 2\n",
    "auth:\n",
    "  plugins: ['auth.anonymous'] #注册认证插件列表\n",
    "  allow-anonymous: true\n",
    "topic-check:\n",
    "  enabled: false  # 禁用topic过滤器\n",
    "```\n",
    "\n",
    "以上配置说明：\n",
    "\n",
    "- 在所有网络接口以 TCP 监听 1883 端口\n",
    "- 发布` $SYS``_ update messages every `` ` 20 秒间隔\n",
    "- 允许匿名登录，禁用topic检查\n",
    "\n",
    "### 配置文件示例\n",
    "\n",
    "```yaml\n",
    "listeners:\n",
    "    default:\n",
    "        max-connections: 50000\n",
    "        type: tcp\n",
    "    my-tcp-1:\n",
    "        bind: 127.0.0.1:1883\n",
    "    my-tcp-2:\n",
    "        bind: 1.2.3.4:1884\n",
    "        max-connections: 1000\n",
    "    my-tcp-ssl-1:\n",
    "        bind: 127.0.0.1:8885\n",
    "        ssl: on\n",
    "        cafile: /some/cafile\n",
    "        capath: /some/folder\n",
    "        capath: certificate data\n",
    "        certfile: /some/certfile\n",
    "        keyfile: /some/key\n",
    "    my-ws-1:\n",
    "        bind: 0.0.0.0:8080\n",
    "        type: ws\n",
    "timeout-disconnect-delay: 2\n",
    "auth:\n",
    "    plugins: ['auth.anonymous'] #List of plugins to activate for authentication among all registered plugins\n",
    "    allow-anonymous: true / false\n",
    "    password-file: /some/passwd_file\n",
    "topic-check:\n",
    "    enabled: true / false  # Set to False if topic filtering is not needed\n",
    "    plugins: ['topic_acl'] #List of plugins to activate for topic filtering among all registered plugins\n",
    "    acl:\n",
    "        # username: [list of allowed topics]\n",
    "        username1: ['repositories/+/master', 'calendar/#', 'data/memes']  # List of topics on which client1 can publish and subscribe\n",
    "        username2: ...\n",
    "        anonymous: []  # List of topics on which an anonymous client can publish and subscribe\n",
    "```\n",
    "\n",
    "配置说明：\n",
    "\n",
    "listeners 段定义了 4 个绑定配置\n",
    "\n",
    "- `my-tcp-2` : 不安全的 TCP 监听端口 1884，允许同时连接 1000 个客户端\n",
    "- `my-tcp-ssl-1` : 安全的 TCP 监听端口 8885，开启 ssl 加密\n",
    "- `my-ws-1` : 不安全的 websocket 监听端口 8080\n",
    "\n",
    "身份验证允许匿名登录和基于密码文件的身份验证。password-file 密码文件必须是文本文件，其中包含用户名和密码，形式为:\n",
    "\n",
    "```sh\n",
    "username:password\n",
    "```\n",
    "\n",
    "其中 `password` 应当加密, 使用`mkpasswd -m sha-512`命令构建编码的口令。\n",
    "\n",
    "密码文件示例：\n",
    "\n",
    "```sh\n",
    "# Test user with 'test' password encrypted with sha-512\n",
    "test:$6$l4zQEHEcowc1Pnv4$HHrh8xnsZoLItQ8BmpFHM4r6q5UqK3DnXp2GaTm5zp5buQ7NheY3Xt9f6godVKbEtA.hOC7IEDwnok3pbAOip.\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "476.727px",
    "left": "57px",
    "top": "110.363px",
    "width": "209.545px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
